/////precompiled////////
#include "precompiled.h"
////////////////////////


#include "prs_Data.h"
using namespace prs;

// TDataDict //////////////////////////////////////////////////////////////////
const char *TDataDict::nodeType_TDataFieldString = "TDataFieldString";
const char *TDataDict::nodeType_TDataFieldInteger = "TDataFieldInteger";
const char *TDataDict::nodeType_TDataFieldDouble = "TDataFieldDouble";
const char *TDataDict::nodeType_TDataFieldDateTime = "TDataFieldDateTime";
//const char *TDataDict::nodeType_TDataFieldRefT = "TDataFieldRefT";
const char *TDataDict::nodeType_TDataFieldRefR = "TDataFieldRefR";
const char *TDataDict::nodeType_TDataFieldRefTR = "TDataFieldRefTR";
const char *TDataDict::nodeType_TDataValueString = "TDataValueString";
const char *TDataDict::nodeType_TDataValueInteger = "TDataValueInteger";
const char *TDataDict::nodeType_TDataValueDouble = "TDataValueDouble";
const char *TDataDict::nodeType_TDataValueDateTime = "TDataValueDateTime";
//const char *TDataDict::nodeType_TDataValueRefT = "TDataValueRefT";
const char *TDataDict::nodeType_TDataValueRefR = "TDataValueRefR";
const char *TDataDict::nodeType_TDataValueRefTR = "TDataValueRefTR";
const char *TDataDict::nodeType_TDataTableRecord = "TDataTableRecord";
//const char *TDataDict::nodeType_TDataRefTRecord = "TDataRefTRecord";
const char *TDataDict::nodeType_TDataRefRRecord = "TDataRefRRecord";
const char *TDataDict::nodeType_TDataRefTRRecord = "TDataRefTRRecord";
const char *TDataDict::nodeType_TDataTable = "TDataTable";
const char *TDataDict::nodeType_TDataTables = "TDataTables";

const char *TDataDict::attrName_Musor = "Musor";
const char *TDataDict::attrName_Musor2 = "Musor2";

const char *TDataDict::attrName_TableId = "TableId";
const char *TDataDict::attrName_FieldId = "FieldId";
const char *TDataDict::attrName_RecordId = "RecordId";

const char *TDataDict::attrName_ToTableId = "ToTableId";
const char *TDataDict::attrName_ToRecordId = "ToRecordId";

const char *TDataDict::attrName_Null = "Null";
const char *TDataDict::attrName_Value = "Value";
const char *TDataDict::attrName_Values = "Values";
const char *TDataDict::attrName_TablePtr = "TablePtr";
const char *TDataDict::attrName_FieldPtr = "FieldPtr";
const char *TDataDict::attrName_Records = "Records";
const char *TDataDict::attrName_Fields = "Fields";
const char *TDataDict::attrName_Size = "Size";
const char *TDataDict::attrName_Tables = "Tables";
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// TDataFieldString ///////////////////////////////////////////////////////////

//
void TDataFieldString::AddValueToTableRecord(TDataTableRecord &Record)
{
  TDataValueString *P = new TDataValueString;
    P->FieldPtr = this;
  Record.Values.Array.Add(P,true);
}

// TDataFieldInteger //////////////////////////////////////////////////////////

//
void TDataFieldInteger::AddValueToTableRecord(TDataTableRecord &Record)
{
  TDataValueInteger *P = new TDataValueInteger;
    P->FieldPtr = this;
  Record.Values.Array.Add(P,true);
}

// TDataFieldDouble ///////////////////////////////////////////////////////////

//
void TDataFieldDouble::AddValueToTableRecord(TDataTableRecord &Record)
{
  TDataValueDouble *P = new TDataValueDouble;
    P->FieldPtr = this;
  Record.Values.Array.Add(P,true);
}

// TDataFieldDateTime /////////////////////////////////////////////////////////

//
void TDataFieldDateTime::AddValueToTableRecord(TDataTableRecord &Record)
{
  TDataValueDateTime *P = new TDataValueDateTime;
    P->FieldPtr = this;
  Record.Values.Array.Add(P,true);
}
/*****************
// TDataFieldRefT /////////////////////////////////////////////////////////////

//
void TDataFieldRefT::AddValueToTableRecord(TDataTableRecord &Record)
{
  TDataValueRefT *P = new TDataValueRefT;
    P->FieldPtr = this;
  Record.Values.Array.Add(P,true);
}
*****************/
// TDataFieldRefR /////////////////////////////////////////////////////////////

//
void TDataFieldRefR::AddValueToTableRecord(TDataTableRecord &Record)
{
  TDataValueRefR *P = new TDataValueRefR;
    P->FieldPtr = this;
  Record.Values.Array.Add(P,true);
}

//
TDataTable *TDataFieldRefR::GetToTable()
{
  return TDataTables::GetTableFromChild(ToTableId,this);
}

// TDataFieldRefTR ////////////////////////////////////////////////////////////

//
void TDataFieldRefTR::AddValueToTableRecord(TDataTableRecord &Record)
{
  TDataValueRefTR *P = new TDataValueRefTR;
    P->FieldPtr = this;
  Record.Values.Array.Add(P,true);
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// TDataFields ////////////////////////////////////////////////////////////////

//
void TDataFields::AddFieldString(const TFieldId &FieldId,int Size) {
  TDataFieldString *P = new TDataFieldString;
    P->FieldId = FieldId.GetId();
    P->TablePtr = dynamic_cast<TDataTable*>(GetOwner());
    P->Size = Size;
  AddField(P);
}

//
void TDataFields::AddFieldInteger(const TFieldId &FieldId) {
  TDataFieldInteger *P = new TDataFieldInteger;
    P->FieldId = FieldId.GetId();
    P->TablePtr = dynamic_cast<TDataTable*>(GetOwner());
  AddField(P);
}

//
void TDataFields::AddFieldDouble(const TFieldId &FieldId) {
  TDataFieldDouble *P = new TDataFieldDouble;
    P->FieldId = FieldId.GetId();
    P->TablePtr = dynamic_cast<TDataTable*>(GetOwner());
  AddField(P);
}

//
void TDataFields::AddFieldDateTime(const TFieldId &FieldId) {
  TDataFieldDateTime *P = new TDataFieldDateTime;
    P->FieldId = FieldId.GetId();
    P->TablePtr = dynamic_cast<TDataTable*>(GetOwner());
  AddField(P);
}

//
TDataFieldRefR *TDataFields::AddFieldRefR(const TFieldId &FieldId,const TTableId &ToTableId) {
  TDataFieldRefR *P = new TDataFieldRefR;
    P->FieldId = FieldId.GetId();
    P->TablePtr = dynamic_cast<TDataTable*>(GetOwner());
    P->ToTableId = ToTableId.GetId();
  AddField(P);
  
  return P;
}

//
TDataFieldRefTR *TDataFields::AddFieldRefTR(const TFieldId &FieldId) {
  TDataFieldRefTR *P = new TDataFieldRefTR;
    P->FieldId = FieldId.GetId();
    P->TablePtr = dynamic_cast<TDataTable*>(GetOwner());
  AddField(P);
  
  return P;
}

//
TDataField *TDataFields::GetField(const TFieldId &FieldId) {
  TNode *P = TNodeSearch(this)
   .SearchByAttrNameAndValue(prs::TDataDict::attrName_FieldId,FieldId.GetId())
    .GetFirst()
  ;
  return dynamic_cast<TDataField*>(P);
}

//
TDataFieldRefR *TDataFields::GetFieldRefR(const TFieldId &FieldId) {
	return dynamic_cast<TDataFieldRefR*>(GetField(FieldId));
}

//
TDataFieldRefTR *TDataFields::GetFieldRefTR(const TFieldId &FieldId) {
	return dynamic_cast<TDataFieldRefTR*>(GetField(FieldId));
}

//
void TDataFields::AddField(TDataField *Field) {
	Add(Field,true);

  TDataTable *Table = dynamic_cast<TDataTable*>(GetOwner());
  TDataTableRecords &Records = Table->Records.Array;

  for (int N = 0; N < Records.Count(); N++) {
		TDataTableRecord &Record = Records.Get(N);
    Field->AddValueToTableRecord(Record);
	}
}

// TDataValue /////////////////////////////////////////////////////////////////

/**********
//
TDataField *TDataValue::GetField() {
  TDataTableRecord *TableRecord = dynamic_cast<TDataTableRecord*>(
		TNodeSearch(this)
		 .SearchNearParentByType(nodeType_TDataTableRecord)
      .GetFirst()
  );
  TDataTable *Table = dynamic_cast<TDataTable*>(
		TNodeSearch(TableRecord)
		 .SearchNearParentByType(nodeType_TDataTable)
      .GetFirst()
  );

	int N = TableRecord->Values.Array.GetNValue(this);
  return &Table->Fields.Array.Get(N);
}
********************/

// TDataValues ////////////////////////////////////////////////////////////////

//
TDataTable *TDataValues::GetTable() {
	if (Count() > 0)	{
		return Get(0).GetField()->GetTable();
	}
	return NULL;
}

//
TDataValue *TDataValues::GetValue(const TFieldId &FieldId) {
	for (int N = 0; N < Count(); N++)	{
		TDataValue &Value = Get(N);
		if (Value.GetField()->FieldId.GetValue().CompareIC(FieldId.GetId())) {
			return &Value;
		}
	}
	return NULL;

/**************
  TNode *P = TNodeSearch(&Values.Array)
   .SearchByAttrNameAndValue(prs::TDataDict::attrName_FieldId,FieldId)
    .GetFirst()
  ;
  return dynamic_cast<TDataValue*>(P);
*************/  
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// TDataTableRecord ///////////////////////////////////////////////////////////

//
TDataValueRefR *TDataTableRecord::GetValueRefR(const TFieldId &FieldId) { 
  return dynamic_cast<TDataValueRefR*>(GetValueByFieldId(FieldId));
}

//
TDataValueRefTR *TDataTableRecord::GetValueRefTR(const TFieldId &FieldId) { 
  return dynamic_cast<TDataValueRefTR*>(GetValueByFieldId(FieldId));
}

//
void TDataTableRecord::SetValueString(const TFieldId &FieldId,svl::TString Value) {
  dynamic_cast<TDataValueString*>(GetValueByFieldId(FieldId))->SetValue(Value);
}

//
void TDataTableRecord::SetValueInteger(const TFieldId &FieldId,int Value) {
  dynamic_cast<TDataValueInteger*>(GetValueByFieldId(FieldId))->SetValue(Value);
}

//
void TDataTableRecord::SetValueDouble(const TFieldId &FieldId,double Value) {
  dynamic_cast<TDataValueDouble*>(GetValueByFieldId(FieldId))->SetValue(Value);
}

//
void TDataTableRecord::SetValueDateTime(const TFieldId &FieldId,svl::TDateTime Value) {
  dynamic_cast<TDataValueDateTime*>(GetValueByFieldId(FieldId))->SetValue(Value);
}

//
TDataRefRRecord *TDataTableRecord::AddValueRefRFirst(
  const TFieldId &FieldId,
  const TRecordId &ToRecordId
){
  TDataValueRefR *Value = GetValueRefR(FieldId);
  return Value->AddRecordFirst(ToRecordId);
}

//
TDataRefRRecord *TDataTableRecord::AddValueRefRLast(
  const TFieldId &FieldId,
  const TRecordId &ToRecordId
){
  TDataValueRefR *Value = GetValueRefR(FieldId);
  return Value->AddRecordLast(ToRecordId);
}

//
TDataRefRRecord *TDataTableRecord::AddValueRefRBefore(
  const TFieldId &FieldId,
  TDataRefRRecord *Current,
  const TRecordId &ToRecordId
){
  TDataValueRefR *Value = GetValueRefR(FieldId);
  return Value->AddRecordBefore(Current,ToRecordId);
}

//
TDataRefRRecord *TDataTableRecord::AddValueRefRAfter(
  const TFieldId &FieldId,
  TDataRefRRecord *Current,
  const TRecordId &ToRecordId
){
  TDataValueRefR *Value = GetValueRefR(FieldId);
  return Value->AddRecordAfter(Current,ToRecordId);
}

//
void TDataTableRecord::AddValueRefTR(
  const TFieldId &FieldId,
  const TTableId &ToTableId,
  const TRecordId &ToRecordId
){
  TDataValueRefTR *Value = GetValueRefTR(FieldId);
    Value->AddRecord(ToTableId,ToRecordId);
}

//
TDataValueString   *TDataTableRecord::GetValueString  (const TFieldId &FieldId) { return dynamic_cast<TDataValueString*>(GetValue(FieldId));}
TDataValueInteger  *TDataTableRecord::GetValueInteger (const TFieldId &FieldId) { return dynamic_cast<TDataValueInteger*>(GetValue(FieldId));}
TDataValueDouble   *TDataTableRecord::GetValueDouble  (const TFieldId &FieldId) { return dynamic_cast<TDataValueDouble*>(GetValue(FieldId));}
TDataValueDateTime *TDataTableRecord::GetValueDateTime(const TFieldId &FieldId) { return dynamic_cast<TDataValueDateTime*>(GetValue(FieldId));}

//
TDataValueString *TDataTableRecord::GetFirstValueString() {
	for (int N = 0; N < Values.Array.Count(); N++) {
		TDataValueString *Value = dynamic_cast<TDataValueString*>(
		  &Values.Array.Get(N)
		);
		if (Value) {
			return Value;
		}
	}
	return NULL;
}

//
void TDataTableRecord::SetValueForExplorer(const svl::TString &in_Value) {
  TDataValueString *Value = GetFirstValueString();
  if (Value) {
		Value->SetValue(in_Value);
  }
}

//
void TDataTableRecord::GetValueForExplorer(svl::TString &out_Value) {
  TDataValueString *Value = GetFirstValueString();
  if (Value) {
		if (!Value->GetNull()) {
			out_Value = Value->GetValue();
			return;
		}
		out_Value = "NULL";
		return;
	}
	out_Value = "error";
}

// TDataTableRecords //////////////////////////////////////////////////////////
/*****
//
TDataTable *TDataTableRecords::GetTable() {
	TDataTable *Table = dynamic_cast<TDataTable*>(GetOwner());

	return Table;

}
**********/
//
TRecordId TDataTableRecords::NewRecordId() {
	int LastRecordId = 0;
	
	int RecordCount = Count();
	if (RecordCount > 0) {
		LastRecordId = Get(RecordCount - 1).RecordId;
	}
	
	return TRecordId(LastRecordId + 1);
}

//
TDataTableRecord *TDataTableRecords::AddRecord(
  const TRecordId &RecordId
){
	TDataTable *Table = dynamic_cast<TDataTable*>(
	  GetOwner()
	);
  TDataFields &Fields = Table->Fields.Array;

  TDataTableRecord *Record = new TDataTableRecord;
    Record->RecordId = RecordId.GetId();
  Add(Record,true);

  for (int N = 0; N < Fields.Count(); N++) {
    TDataField &Field = Fields.Get(N);
    Field.AddValueToTableRecord(*Record);
  }

  return Record;
}

//
TDataTableRecord *TDataTableRecords::GetRecord(
	const TRecordId &RecordId
){
  for (int N = 0; N < Count(); N++) {
    TDataTableRecord &Record = Get(N);
    if (Record.RecordId == RecordId.GetId()) {
      return &Record;
    }
  }
  return NULL;
}

/****************
// TDataRefTRecord ////////////////////////////////////////////////////////////

//
TDataTable *TDataRefTRecord::GetToTable() {
  return TDataTables::GetTableFromChild(ToTableId.GetValue(),this);
}

// TDataRefTRecords ///////////////////////////////////////////////////////////

//
TDataRefTRecord *TDataRefTRecords::AddRecord(
  char *ToTableId
){
  TDataRefTRecord *Record = new TDataRefTRecord;
    Record->ToTableId = ToTableId;
  Add(Record,true);
  
  return Record;
}

//
TDataRefTRecord *TDataRefTRecords::GetRecord(
  char *ToTableId
){
  for (int N = 0; N < Count(); N++) {
    TDataRefTRecord &Record = Get(N);
    if (Record.ToTableId.GetValue().CompareIC(ToTableId)) {
      return &Record;
    }
  }
  return NULL;
}
*********************/
// TDataRefRRecord ///////////////////////////////////////////////////////////

//
TDataTable *TDataRefRRecord::GetToTable() {
  TNode *P = TNodeSearch(this)
  .SearchNearParentByType(nodeType_TDataValueRefR)
   .GetFirst()
  ;
  TDataValueRefR *ValueRefR	= dynamic_cast<TDataValueRefR*>(P);
  return ValueRefR->FieldPtr.GetValue()->GetToTable();
}

//
TDataTableRecord *TDataRefRRecord::GetToRecord() {
  TDataTable *ToTable = GetToTable(); 
  if (ToTable) {
    return ToTable->Records.Array.GetRecord(ToRecordId.GetValue());
  }
  return NULL;
}

// TDataRefRRecords ///////////////////////////////////////////////////////////

//
TDataTableRecord *TDataRefRRecords::GetToRecord(int N) {
  TDataRefRRecord &Record = Get(N);
  TDataTable *ToTable = Record.GetToTable();

  return ToTable->Records.Array.GetRecord( TRecordId(Record.ToRecordId) );
}

/****************
//
void TDataRefRRecords::GetToRecords(TDataTableRecords &ToRecords) {
	ToRecords.Clear();
	TDataTable *ToTable = NULL;
	
	for (int N = 0; N < Count(); N++)	{
    TDataRefRRecord &Record = Get(N);
	
		if (!ToTable) {
      ToTable = Record.GetToTable();
    }
	
    ToRecords.Add(
      ToTable->Records.Array.GetRecord(Record.ToRecordId),false
    );
	}
}
******************/

//
TDataRefRRecord *TDataRefRRecords::AddRecordFirst(
  const TRecordId &ToRecordId
){
  TDataRefRRecord *Record = new TDataRefRRecord;
    Record->ToRecordId = ToRecordId.GetId();
  AddFirst(Record,true);
  
  return Record;
}

//
TDataRefRRecord *TDataRefRRecords::AddRecordLast(
  const TRecordId &ToRecordId
){
  TDataRefRRecord *Record = new TDataRefRRecord;
    Record->ToRecordId = ToRecordId.GetId();
  AddLast(Record,true);
  
  return Record;
}

//
TDataRefRRecord *TDataRefRRecords::AddRecordBefore(
  TDataRefRRecord *Current,
  const TRecordId &ToRecordId
){
  TDataRefRRecord *Record = new TDataRefRRecord;
    Record->ToRecordId = ToRecordId.GetId();
  AddBefore(Record,Current,true);
  
  return Record;
}

//
TDataRefRRecord *TDataRefRRecords::AddRecordAfter(
  TDataRefRRecord *Current,
  const TRecordId &ToRecordId
){
  TDataRefRRecord *Record = new TDataRefRRecord;
    Record->ToRecordId = ToRecordId.GetId();
  AddAfter(Record,Current,true);
  
  return Record;
}

//
TDataRefRRecord *TDataRefRRecords::GetRecord(
  const TRecordId &ToRecordId
){
  for (int N = 0; N < Count(); N++) {
    TDataRefRRecord &Record = Get(N);
    if (Record.ToRecordId == ToRecordId.GetId()) {
      return &Record;
    }
  }
  return NULL;
}

// TDataRefTRRecord ///////////////////////////////////////////////////////////

//
TDataTable *TDataRefTRRecord::GetToTable() {
  return TDataTables::GetTableFromChild(ToTableId,this);
}

//
TDataTableRecord *TDataRefTRRecord::GetToRecord() {
  TDataTable *ToTable = GetToTable(); 
  if (ToTable) {
    return ToTable->Records.Array.GetRecord( TRecordId(ToRecordId) );
  }
  return NULL;
}

// TDataRefTRRecords //////////////////////////////////////////////////////////

/**************
//
void TDataRefTRRecords::GetToRecords(
  TDataTableRecords &ToRecords
){
	ToRecords.Clear();
	
	for (int N = 0; N < Count(); N++)	{
    TDataRefTRRecord &Record = Get(N);
	
    TDataTable *ToTable = Record.GetToTable();
	
    ToRecords.Add(
      ToTable->Records.Array.GetRecord(Record.ToRecordId),false
    );
	}
}
*********************/

//
TDataRefTRRecord *TDataRefTRRecords::AddRecord(
  const TTableId &ToTableId,
  const TRecordId &ToRecordId
){
  TDataRefTRRecord *Record = new TDataRefTRRecord;
    Record->ToTableId  = ToTableId.GetId();
    Record->ToRecordId = ToRecordId.GetId();
  Add(Record,true);
  
  return Record;
}

//
TDataRefTRRecord *TDataRefTRRecords::GetRecord(
  const TTableId &ToTableId,
  const TRecordId &ToRecordId
){
  for (int N = 0; N < Count(); N++) {
    TDataRefTRRecord &Record = Get(N);
    if (Record.ToRecordId == ToRecordId.GetId() && Record.ToTableId.GetValue().CompareIC(ToTableId.GetId())) {
      return &Record;
    }
  }
  return NULL;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// TDataValueString ///////////////////////////////////////////////////////////

// TDataValueInteger //////////////////////////////////////////////////////////

// TDataValueDouble ///////////////////////////////////////////////////////////

// TDataValueDateTime /////////////////////////////////////////////////////////

// TDataValueRefT /////////////////////////////////////////////////////////////

// TDataValueRefR /////////////////////////////////////////////////////////////

// TDataValueRefTR ////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// TDataTable /////////////////////////////////////////////////////////////////

// TDataTables ////////////////////////////////////////////////////////////////

//
TDataTable *TDataTables::AddTable(const TTableId &TableId) 
{ 
  TDataTable *P = new TDataTable; 
    P->TableId = TableId.GetId(); 
  Tables.Array.Add(P,true); 

  return P;
}

//
TDataTable *TDataTables::GetTable(const TTableId &TableId) 
{ 
  TNode *P = TNodeSearch(&Tables.Array)
   .SearchByAttrNameAndValue(TDataDict::attrName_TableId,TableId.GetId())
    .GetFirst()
  ;
  return dynamic_cast<TDataTable*>(P);
}

//
TDataTable *TDataTables::GetTableFromChild(const TTableId &TableId,TNode *FromChild)
{
  TNode *PTable = TNodeSearch(FromChild)
  .SearchNearParentByType(nodeType_TDataTables)
    .GotoChildren(attrName_Tables)
     .SearchByAttrNameAndValue(prs::TDataDict::attrName_TableId,TableId.GetId())
      .GetFirst()
  ;
  
  if (!PTable) {
    TDataTables().Except("GetTableFromChild[!PTable]");
  }

  TDataTable *Table = dynamic_cast<TDataTable*>(PTable);

  if (!Table) {
    TDataTables().Except("GetTableFromChild[!Table]");
  }
  
  return Table;
}

